/*
 ------------------------------------------------------------------------------
 Copyright (C) 2013 Eternal Games.

 This file is part of the GLQuake source code.

 The GLQuake source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The GLQuake source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the GLQuake source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// cg_event.cpp - entity events received from the server-game
//


#include "cg_local.h"


static const char *	cg_eventNames[64] = {
	"EV_NONE",
	"EV_JUMP",
	"EV_STEP",
	"EV_PLAYSOUND",
	"EV_STOPSOUND",
	"EV_PROJECTILE",
	"EV_FIRE_WEAPON",
	"EV_GIB"
};


/*
 ==================

 ==================
*/
static void CG_JumpEvent (entity_t *entity, int parm){

	// TODO: play a jump sound from the emitter (player)
}

/*
 ==================

 ==================
*/
static void CG_StepEvent (entity_t *entity, int parm){

}

/*
 ==================
 CG_PlaySoundEvent
 ==================
*/
static void CG_PlaySoundEvent (entity_t *entity, int parm){

	soundShader_t	*soundShader;
	int				channel;

	if (!entity->emitterHandle)
		return;

	channel = (parm >> 12) & 15;

	// Get the sound shader
	soundShader = cgs.gameSoundShaders[parm & (MAX_GAME_SOUND_SHADERS - 1)];
	if (!soundShader)
		return;

	// Play a sound on the given channel
	glqSound->PlaySoundFromEmitter(entity->emitterHandle, channel, cg.time, soundShader);
}

/*
 ==================
 CG_StopSoundEvent
 ==================
*/
static void CG_StopSoundEvent (entity_t *entity, int parm){

	soundShader_t	*soundShader;
	int				channel;

	if (!entity->emitterHandle)
		return;

	channel = (parm >> 12) & 15;

	// Get the sound shader
	soundShader = cgs.gameSoundShaders[parm & (MAX_GAME_SOUND_SHADERS - 1)];
	if (!soundShader)
		return;

	// Stop all sounds on the given channel
	glqSound->StopSoundFromEmitter(entity->emitterHandle, channel);
}

/*
 ==================

 ==================
*/
static void CG_ProjectileEvent (entity_t *entity, int parm){

}

/*
 ==================

 NOTE: this function will handle sounds, and brass ejection?.

 NOTE: how do we handle the frames?, Quake plays a sound on a specific frame.
 Do we pass down the frame from the server-game to here?, then handle it all?

 NOTE: this means we send A LOT of events per-frame when firing a weapon
 ==================
*/
static void CG_FireWeaponEvent (entity_t *entity, int parm){

	// Play a sound
	CG_FireWeaponSound(entity);
}

/*
 ==================

 NOTE: spawn effects here
 ==================
*/
static void CG_GibEvent (entity_t *entity, int parm){

}


// ============================================================================


/*
 ==================
 CG_EntityEvent
 ==================
*/
void CG_EntityEvent (entity_t *entity, int eventType, int eventParm){

	if (cg_showEvents->integerValue){
		if (!cg_eventNames[eventType])
			G_Printf("%4i: BAD EVENT %i\n", entity->state->number, eventType);
		else
			G_Printf("%4i: %s\n", entity->state->number, cg_eventNames[eventType]);
	}

	switch (eventType){
	case EV_NONE:

		break;
	case EV_JUMP:
		CG_JumpEvent(entity, eventParm);
		break;
	case EV_STEP:
		CG_StepEvent(entity, eventParm);
		break;
	case EV_PLAYSOUND:
		CG_PlaySoundEvent(entity, eventParm);
		break;
	case EV_STOPSOUND:
		CG_StopSoundEvent(entity, eventParm);
		break;
	case EV_PROJECTILE:
		CG_ProjectileEvent(entity, eventParm);
		break;
	case EV_FIRE_WEAPON:
		CG_FireWeaponEvent(entity, eventParm);
		break;
	case EV_GIB:
		CG_GibEvent(entity, eventParm);
		break;
	default:
		G_Error("CG_EntityEvent: bad event type (%i)", eventType);
	}
}

/*
 ==================
 CG_CheckEntityEvents
 ==================
*/
void CG_CheckEntityEvents (){

	entity_t	*entity;
	int			index;
	int			i, j;

	if (!cg.checkEvents)
		return;
	cg.checkEvents = false;

	// Go through all the active entities
	for (i = 0; i < cg.numActiveEntities; i++){
		entity = cg.activeEntities[i];

		// If it should be ignored for anything other than binding
		if (entity->state->flags & EF_IGNORE){
			entity->eventSequence = entity->state->eventSequence;
			continue;
		}

		// Check the entity's event queue
		if (entity->state->eventSequence - entity->eventSequence > MAX_EVENTS)
			entity->eventSequence = entity->state->eventSequence - MAX_EVENTS;

		for (j = entity->eventSequence; j != entity->state->eventSequence; j++){
			index = j & (MAX_EVENTS - 1);

			CG_EntityEvent(entity, entity->state->eventTypes[index], entity->state->eventParms[index]);
		}

		entity->eventSequence = entity->state->eventSequence;
	}
}